package flc.ast.activity;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.View;

import com.blankj.utilcode.util.FileUtils;
import com.blankj.utilcode.util.ImageUtils;
import com.blankj.utilcode.util.ToastUtils;
import com.lxj.xpopup.XPopup;
import com.lxj.xpopup.interfaces.OnSelectListener;
import com.stark.mindmap.lib.core.layout.BoxDownTreeLayoutManager;
import com.stark.mindmap.lib.core.layout.BoxHorizonLeftAndRightLayoutManager;
import com.stark.mindmap.lib.core.layout.BoxLeftTreeLayoutManager;
import com.stark.mindmap.lib.core.layout.BoxRightTreeLayoutManager;
import com.stark.mindmap.lib.core.layout.BoxUpTreeLayoutManager;
import com.stark.mindmap.lib.core.layout.BoxVerticalUpAndDownLayoutManager;
import com.stark.mindmap.lib.core.layout.MindLayoutType;
import com.stark.mindmap.lib.core.layout.TreeLayoutManager;
import com.stark.mindmap.lib.core.line.BaseLine;
import com.stark.mindmap.lib.core.line.SmoothLine;
import com.stark.mindmap.lib.core.model.DefNodeData;
import com.stark.mindmap.lib.core.model.LayoutTreeModel;
import com.stark.mindmap.lib.core.model.NodeModel;
import com.stark.mindmap.lib.core.model.TreeModel;
import com.stark.mindmap.lib.core.util.MindPrefUtil;
import com.stark.mindmap.lib.core.util.MindUtil;
import com.stark.mindmap.lib.ui.MindAddEditDialog;
import com.stark.mindmap.lib.ui.MindEditActivity;
import com.stark.mindmap.lib.ui.MindSaveDialog;
import com.stark.mindmap.lib.ui.MyTreeViewAdapter;

import flc.ast.BaseAc;
import flc.ast.HomeActivity;
import flc.ast.R;
import flc.ast.databinding.ActivityMindMapBinding;
import flc.ast.dialog.MyMindAddEditDialog;
import flc.ast.dialog.MyMindSaveDialog;
import flc.ast.utils.Content;
import stark.common.basic.constant.Extra;
import stark.common.basic.utils.FastClickUtil;
import stark.common.basic.utils.FileP2pUtil;
import stark.common.basic.utils.FileUtil;

public class MindMapActivity extends BaseAc<ActivityMindMapBinding> {

    private MyTreeViewAdapter mAdapter;
    private String filePath;
    private boolean isChanged = true;
    private MindLayoutType mCurLayoutType;


    public static void start(Context context, String filePath) {
        Intent intent = new Intent(context, MindMapActivity.class);
        if (!TextUtils.isEmpty(filePath)) {
            intent.putExtra(Extra.PATH, filePath);
        }
        context.startActivity(intent);
    }

    @Override
    protected int onCreate() {
        return R.layout.activity_mind_map;
    }

    @Override
    protected void initView() {
        mDataBinding.ivMindMapBack.setOnClickListener(v -> onBackPressed());

        LayoutTreeModel<DefNodeData> layoutTreeModel = createTreeModel();
        mCurLayoutType = layoutTreeModel.type;
        mDataBinding.treeView.setTreeLayoutManager(getTreeLayoutManager(layoutTreeModel.type));
        //adapter
        MyTreeViewAdapter adapter = new MyTreeViewAdapter();
        mAdapter = adapter;
        adapter.setItemLongClickListener((view, model) -> {
            showEditNodeDialog(model);
        });
        mDataBinding.treeView.setAdapter(adapter);
        //注意：这里必须要让adapter先设置进treeView后再设置treeModel，否则无法显示出来数据
        adapter.setTreeModel(layoutTreeModel.treeModel);

        if (MindPrefUtil.isFirstOpen()) {
            mDataBinding.treeView.post(() -> {
                ToastUtils.showShort(R.string.mdm_long_press_node_tip);
                MindPrefUtil.setFirstOpen(false);
            });
        }

        mDataBinding.ivSave.setOnClickListener(this);
        mDataBinding.tvAddNode.setOnClickListener(this);
        mDataBinding.tvAddSubNode.setOnClickListener(this);
        mDataBinding.tvLocCenter.setOnClickListener(this);
        mDataBinding.tvLayout.setOnClickListener(this);
    }

    @Override
    protected void onClickCallback(View v) {
        switch (v.getId()) {
            case R.id.ivSave://保存
                handleClickExport();
                break;
            case R.id.tvAddNode://同级节点
                handleClickAddNode();
                break;
            case R.id.tvAddSubNode://子节点
                handleClickAddSubNode();
                break;
            case R.id.tvLocCenter://布局居中
                mDataBinding.treeView.getEditor().focusMidLocation();
                break;
            case R.id.tvLayout://选择布局
                showLayoutMenu(v);
                break;
        }
    }

    @Override
    protected void initData() {

    }

    private LayoutTreeModel<DefNodeData> createTreeModel() {
        Intent intent = getIntent();
        String filePath = intent.getStringExtra(Extra.PATH);
        if (TextUtils.isEmpty(filePath) || !FileUtils.isFileExists(filePath)) {
            LayoutTreeModel<DefNodeData> layoutTreeModel = new LayoutTreeModel<>();
            layoutTreeModel.type = MindLayoutType.RIGHT;
            isChanged = true;
            DefNodeData rootNodeData = new DefNodeData();
            rootNodeData.text = getString(R.string.mdm_theme);
            NodeModel<DefNodeData> rootNodeModel = new NodeModel<>(rootNodeData);
            TreeModel<DefNodeData> treeModel = new TreeModel<>(rootNodeModel);
            layoutTreeModel.treeModel = treeModel;
            return layoutTreeModel;
        }
        this.filePath = filePath;
        isChanged = false;
        return MindUtil.getTreeModelFromFile(filePath);
    }

    private TreeLayoutManager getTreeLayoutManager(MindLayoutType type) {
        int spaceParent2Child = 30;
        int spaceChild2Child = 20;
        BaseLine line = new SmoothLine();
        TreeLayoutManager layoutManager = null;
        switch (type) {
            case LEFT:
                layoutManager = new BoxLeftTreeLayoutManager(this, spaceParent2Child, spaceChild2Child, line);
                break;
            case UP:
                layoutManager = new BoxUpTreeLayoutManager(this, spaceParent2Child, spaceChild2Child, line);
                break;
            case DOWN:
                layoutManager = new BoxDownTreeLayoutManager(this, spaceParent2Child, spaceChild2Child, line);
                break;
            case LEFT_RIGHT:
                layoutManager = new BoxHorizonLeftAndRightLayoutManager(this, spaceParent2Child, spaceChild2Child, line);
                break;
            case UP_DOWN:
                layoutManager = new BoxVerticalUpAndDownLayoutManager(this, spaceParent2Child, spaceChild2Child, line);
                break;
            default:
                layoutManager = new BoxRightTreeLayoutManager(this, spaceParent2Child, spaceChild2Child, line);
                break;
        }
        return layoutManager;
    }

    private void handleClickAddNode() {
        if (mAdapter.isCurSelNodeModelRoot()) {
            ToastUtils.showShort(getString(R.string.mdm_root_node_add_node_tip));
            return;
        }
        if (mAdapter.getCurSelNodeModel() == null) {
            ToastUtils.showShort(R.string.mdm_sel_node_first);
            return;
        }
        showAddNodeDialog(false);
    }

    private void handleClickAddSubNode() {
        if (mAdapter.getCurSelNodeModel() == null) {
            ToastUtils.showShort(R.string.mdm_sel_node_first);
            return;
        }
        showAddNodeDialog(true);
    }

    private LayoutTreeModel<DefNodeData> getLayoutTreeModel() {
        LayoutTreeModel<DefNodeData> layoutTreeModel = new LayoutTreeModel<>();
        layoutTreeModel.type = mCurLayoutType;
        layoutTreeModel.treeModel = mAdapter.getTreeModel();
        return layoutTreeModel;
    }

    private void showAddNodeDialog(boolean isAddSubNode) {
        MyMindAddEditDialog addDialog = MyMindAddEditDialog.createAddDialog(this, isAddSubNode);
        addDialog.setListener(new MyMindAddEditDialog.IListener() {
            @Override
            public void onConfirm(@NonNull DefNodeData nodeData) {
                isChanged = true;
                if (isAddSubNode) {
                    mDataBinding.treeView.getEditor().addChildNodes(mAdapter.getCurSelNodeModel(), new NodeModel<>(nodeData));
                } else {
                    mDataBinding.treeView.getEditor().addChildNodes(mAdapter.getCurSelNodeModel().getParentNode(), new NodeModel<>(nodeData));
                }
            }

            @Override
            public void onDelNode() {
            }
        });
        DefNodeData nodeData = new DefNodeData();
        nodeData.text = getString(R.string.mdm_new_node);
        addDialog.setNodeData(nodeData);
        addDialog.show();
    }

    private void showLayoutMenu(View view) {
        int[] titleIds = new int[]{R.string.mdm_left, R.string.mdm_right, R.string.mdm_up, R.string.mdm_down,
                R.string.mdm_left_right, R.string.mdm_up_down};
        String[] titles = new String[titleIds.length];
        for (int i = 0; i < titles.length; i++) {
            titles[i] = getResources().getString(titleIds[i]);
        }
        new XPopup.Builder(this)
                .hasShadowBg(false)
                .isTouchThrough(true)
                .isDestroyOnDismiss(true) //对于只使用一次的弹窗，推荐设置这个
                .atView(view)
                .isCenterHorizontal(false)
                .hasShadowBg(false) // 去掉半透明背景
                .asAttachList(titles, null, new OnSelectListener() {
                    @Override
                    public void onSelect(int position, String text) {
                        MindLayoutType layoutType = MindLayoutType.getByPos(position);
                        if (layoutType != mCurLayoutType) {
                            isChanged = true;
                            mCurLayoutType = layoutType;
                            mDataBinding.treeView.setTreeLayoutManager(getTreeLayoutManager(layoutType));
                            mAdapter.notifyDataSetChange();
                        }
                    }
                })
                .setContentGravity(Gravity.LEFT)
                .show();

    }

    private void showEditNodeDialog(@NonNull NodeModel<DefNodeData> nodeModel) {
        MyMindAddEditDialog editDialog = MyMindAddEditDialog.createEditDialog(this);
        editDialog.setListener(new MyMindAddEditDialog.IListener() {
            @Override
            public void onConfirm(@NonNull DefNodeData nodeData) {
                nodeModel.setValue(nodeData);
                mAdapter.notifyDataSetChange();
                isChanged = true;
                //下面这行代码不起作用，因为内部没有做真正的实现
                //mAdapter.notifyItemViewChange(nodeModel);
            }

            @Override
            public void onDelNode() {
                if (mAdapter.getTreeModel().getRootNode() == nodeModel) {
                    ToastUtils.showShort(R.string.mdm_del_root_node_tip);
                    return;
                }
                mDataBinding.treeView.getEditor().removeNode(nodeModel);
                mAdapter.setCurSelNodeModel(null);
                isChanged = true;
            }
        });
        editDialog.setNodeData(nodeModel.getValue());
        editDialog.show();
    }

    private void handleClickExport() {
        if (FastClickUtil.isFastClick()) {
            return;
        }
        Bitmap bitmap = ImageUtils.view2Bitmap(mDataBinding.treeView);
        String filePath = FileUtil.generateFilePath(Content.myMindMapRecord, ".png");
        ImageUtils.save(bitmap, filePath, Bitmap.CompressFormat.PNG);
        ToastUtils.showShort(R.string.save_success);
        startActivity(HomeActivity.class);
    }

    private void handleClickSave() {
        if (FastClickUtil.isFastClick()) {
            return;
        }
        if (TextUtils.isEmpty(filePath)) {
            MyMindSaveDialog dialog = new MyMindSaveDialog(this);
            dialog.setListener(() -> {
                isChanged = false;
            });
            dialog.setLayoutTreeModel(getLayoutTreeModel());
            dialog.show();
        } else {
            String fileName = FileUtils.getFileNameNoExtension(filePath);
            boolean ret = MindUtil.saveTreeModel2File(fileName, getLayoutTreeModel());
            if (ret) {
                isChanged = false;
            }
            ToastUtils.showShort(ret ? com.stark.common.res.R.string.save_success : com.stark.common.res.R.string.save_failure);
        }
    }

}